import {nextTick, reactive, ref} from 'vue'
import * as u from '@/util/util'
import {HttpService} from '@/util/httpService'
import {ElMessage, ElMessageBox} from 'element-plus'

const httpService = new HttpService()

export const FUN_TYPE = {
    ADD: 'add',
    DEL: 'del',
    UPDATE: 'update',
    GET_LIST: 'getList'
}


/**
 * table统一封装
 * @param tableOption
 * @param apiUrl
 * @param options
 * @returns {{sizeChange: sizeChange, refreshChange: (function(): *), handleUpdate: (*|(function(*, *, *, *): void)|(function(*, *, *, *): void)), tableData: *, rowDel: ((function(*): void)|*|(function(*): void)), tableLoading: *, searchForm: *, url: *, handleSave: (*|(function(*, *, *): void)|(function(*, *, *): void)), form: *, searchChange: searchChange, page: *, refName: *, buttonPermissionsCheck: ((function(*): boolean)|*), currentChange: currentChange, activated: activated}}
 */
export function useTableMixins(tableOption, apiUrl, options = {}) {
    //表格编辑表单
    const form = ref({})
    //表格请求前置
    const url = ref(apiUrl)
    //权限检验方法
    const buttonPermissionsCheck = u.buttonPermissionsCheck
    //查询接口地址
    const listUrl = ref(options.listUrl ?? 'findPage')
    //新增接口地址
    const addUrl = ref(options.addUrl ?? 'add')
    //删除接口地址
    const delUrl = ref(options.delUrl ?? 'delete-by-id')
    //修改接口地址
    const updateUrl = ref(options.updateUrl ?? 'update')
    //表格ref
    const refName = ref(options.refName ?? 'crud')
    //查询默认参数
    const defaultParameter = ref(options.defaultParameter ?? {})
    //保存默认参数
    const saveDefaultParameter = ref(options.saveDefaultParameter ?? {})
    //是否默认查询
    const isGetList = ref(options.isGetList ?? true)
    // page 参数可自定义
    const page = reactive(
        options.page ?? {
            total: 0,
            currentPage: 1,
            pageSize: 20,
            sortdatafield: 'create_date',
            sortorder: 'desc',
        }
    )

    //表格加载loading
    const tableLoading = ref(false)
    //表格数据
    const tableData = ref([])
    //查询条件
    const searchForm = ref({...(options.searchForm || {})})

    // 删除 $ 开头的字段
    const del$ = (obj) => {
        const row = u.copyBean(obj)
        Object.keys(row).forEach(key => {
            if (key.startsWith('$')) {
                delete row[key]
            }
        })
        return row
    }

    //删除不展示的字段
    const delNotField = (data, type) => {
        const row = u.copyBean(data)
        tableOption.column.forEach(col => {
            if (!Object.keys(row).includes(col.prop)) return

            if ((type === 'add' && col.addDisplay === false && col.label !== 'ID') ||
                (type === 'update' && col.editDisplay === false && col.label !== 'ID')) {
                delete row[col.prop]
            }
        })

        Object.keys(row).forEach(key => {
            if (!tableOption.column.some(col => col.prop === key)) {
                delete row[key]
            }
        })

        return row
    }

    //获取id字段
    const getIdField = () => {
        const idCol = tableOption.column.find(col => col.label === 'ID')
        return idCol ? idCol.prop : 'id'
    }


    /**
     * 定义默认插叙方法
     * @type {*|(function(): void)}
     */
    const getList = options.getList || (() => {
        tableLoading.value = true
        const query = {...searchForm.value, ...page, ...defaultParameter.value}
        httpService.get(`/${url.value}/${listUrl.value}`, query)
            .then(res => {
                tableData.value = res.records
                page.total = res.total
                //方法执行完毕通知
                funExecuteCompleted(FUN_TYPE.GET_LIST, res);
            })
            .finally(() => {
                tableLoading.value = false
                //方法执行完毕通知
                funExecuteCompleted(FUN_TYPE.GET_LIST, {});
            })
    })

    /**
     * 定义默认保存方法
     * @type {(function(*, *, *): void)|*|(function(*, *, *): void)}
     */
    const handleSave = options.handleSave || ((row, done, loading) => {
        let obj = Object.assign({}, delNotField(del$(row), 'add'), saveDefaultParameter.value)
        httpService.post(`/${url.value}/${addUrl.value}`, obj)
            .then(() => {
                ElMessage.success('新增成功')
                getList()
                done(form)
                //方法执行完毕通知
                funExecuteCompleted(FUN_TYPE.ADD, obj);
            }).catch(() => {
            //方法执行完毕通知
            funExecuteCompleted(FUN_TYPE.ADD, obj);
            loading()
        })
    })

    /**
     * 定义默认修改方法
     * @type {(function(*, *, *, *): void)|*|(function(*, *, *, *): void)}
     */
    const handleUpdate = options.handleUpdate || ((row, index, done, loading) => {
        let obj = Object.assign({}, delNotField(del$(row), 'update'), saveDefaultParameter.value)
        httpService.put(`/${url.value}/${updateUrl.value}`, obj)
            .then(() => {
                ElMessage.success('修改成功')
                getList()
                done(form);
                //方法执行完毕通知
                funExecuteCompleted(FUN_TYPE.UPDATE, obj);
            })
            .catch(() => {
                loading()
                //方法执行完毕通知
                funExecuteCompleted(FUN_TYPE.UPDATE, obj);
            })
    })

    /**
     * 定义默认删除方法
     * @type {(function(*): void)|*|(function(*): void)}
     */
    const rowDel = options.rowDel || ((row) => {
        ElMessageBox.confirm('是否确认删除？', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        }).then(() => {
            const id = row[getIdField()]
            httpService.del(`/${url.value}/${delUrl.value}/${id}`)
                .then(() => {
                    ElMessage.success('删除成功')
                    getList()
                    //方法执行完毕通知
                    funExecuteCompleted(FUN_TYPE.DEL, id);
                }).catch(() => {
                //方法执行完毕通知
                funExecuteCompleted(FUN_TYPE.DEL, id);
            })
        })
    })

    /**
     * 方法执行完毕通知
     * @param funType 方法类型
     * @param obj   返回数据
     */
    const funExecuteCompleted = (funType, obj) => {
        //方法执行完毕，回调通知
        if (options.funExecuteCompleted) {
            options.funExecuteCompleted(funType, obj);
        }
    }


    /**
     * 查询变化方法
     * @param form
     * @param done
     */
    const searchChange = (form, done) => {
        searchForm.value = form;
        page.currentPage = 1
        getList()
        if (done) {
            done(form)
        }

    }

    /**
     * 清楚查询方法
     * @returns {*}
     */
    const refreshChange = () => getList()

    /**
     * 分页变化回调
     * @param val
     */
    const sizeChange = (val) => {
        page.pageSize = val
        page.currentPage = 1
        getList()
    }

    /**
     * 当前页变化回调
     * @param val
     */
    const currentChange = (val) => {
        page.currentPage = val
        getList()
    }

    const activated = () => {
        nextTick(() => {
            refName.value?.doLayout?.()
        })
    }

    // 自动在生命周期内调用 getList
    onMounted(() => {
        if (isGetList.value) {
            getList()
        }
    })

    return {
        form,
        refName,
        page,
        tableData,
        tableLoading,
        searchForm,
        handleSave,
        handleUpdate,
        rowDel,
        searchChange,
        refreshChange,
        sizeChange,
        currentChange,
        activated,
        url,
        buttonPermissionsCheck,
        getList
    }
}
